﻿namespace WinnerCMS.Common.Security
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Threading;

    internal static class HtmlParameterEncoder
    {
        private static char[][] characterValues;
        private static readonly char[] FormStringSpace = "+".ToCharArray();
        private static readonly char[] QueryStringSpace = "%20".ToCharArray();
        private static readonly ReaderWriterLockSlim SyncLock = new ReaderWriterLockSlim();

        private static void AcquireReadLock()
        {
            SyncLock.EnterReadLock();
        }

        private static void AcquireWriteLock()
        {
            SyncLock.EnterWriteLock();
        }

        private static string FormQueryEncode(string s, Encoding encoding, EncodingType encodingType, char[][] safeList)
        {
            if (string.IsNullOrEmpty(s))
            {
                return s;
            }
            if (encoding == null)
            {
                throw new ArgumentNullException("encoding");
            }
            byte[] bytes = encoding.GetBytes(s.ToCharArray());
            char[] chArray = new char[bytes.Length * 3];
            int length = 0;
            AcquireReadLock();
            try
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    char[] queryStringSpace;
                    int num4;
                    byte index = bytes[i];
                    if (((index != 0) && (index != 0x20)) && ((index <= safeList.Length) && (safeList[index] == null)))
                    {
                        goto Label_00BE;
                    }
                    if (index == 0x20)
                    {
                        switch (encodingType)
                        {
                            case EncodingType.QueryString:
                                queryStringSpace = QueryStringSpace;
                                goto Label_009D;

                            case EncodingType.HtmlForm:
                                queryStringSpace = FormStringSpace;
                                goto Label_009D;
                        }
                        throw new ArgumentOutOfRangeException("encodingType");
                    }
                    queryStringSpace = characterValues[index];
                Label_009D:
                    num4 = 0;
                    while (num4 < queryStringSpace.Length)
                    {
                        chArray[length++] = queryStringSpace[num4];
                        num4++;
                    }
                    continue;
                Label_00BE:
                    chArray[length++] = (char) index;
                }
            }
            finally
            {
                ReleaseReadLock();
            }
            return new string(chArray, 0, length);
        }

        internal static string FormStringParameterEncode(string s, Encoding encoding)
        {
            if (characterValues == null)
            {
                InitialiseParameterSafeList();
            }
            return FormQueryEncode(s, encoding, EncodingType.HtmlForm, characterValues);
        }

        private static void InitialiseParameterSafeList()
        {
            AcquireWriteLock();
            try
            {
                characterValues = SafeList.Generate(0xff, new SafeList.GenerateSafeValue(SafeList.PercentThenHexValueGenerator));
                SafeList.PunchSafeList(ref characterValues, UrlParameterSafeList());
            }
            finally
            {
                ReleaseWriteLock();
            }
        }

        internal static string QueryStringParameterEncode(string s, Encoding encoding)
        {
            if (characterValues == null)
            {
                InitialiseParameterSafeList();
            }
            return FormQueryEncode(s, encoding, EncodingType.QueryString, characterValues);
        }

        private static void ReleaseReadLock()
        {
            SyncLock.ExitReadLock();
        }

        private static void ReleaseWriteLock()
        {
            SyncLock.ExitWriteLock();
        }

        private static IEnumerable UrlParameterSafeList()
        {
            yield return 0x2d;
            yield return 0x2e;
            int iteratorVariable0 = 0x30;
        Label_PostSwitchInIterator:;
            if (iteratorVariable0 <= 0x39)
            {
                yield return iteratorVariable0;
                iteratorVariable0++;
                goto Label_PostSwitchInIterator;
            }
            for (int i = 0x41; i <= 90; i++)
            {
                yield return i;
            }
            yield return 0x5f;
            for (int j = 0x61; j <= 0x7a; j++)
            {
                yield return j;
            }
            yield return 0x7e;
        }

    }
}

